
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "esp_vfs_semihost.h"
#include "esp_vfs_fat.h"
#include "esp_spiffs.h"
#include "sdmmc_cmd.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_log.h"
#include "mdns.h"
#include "lwip/apps/netbiosns.h"
#include "protocol_examples_common.h"
#include "cJSON.h"

#include "network_manager.h"
#include "app_uart.h"
#include "tcp_server.h"

#define MDNS_INSTANCE "esp home web server"
#define EXAMPLE_MDNS_HOST_NAME "esp-home"
#define EXAMPLE_WEB_MOUNT_POINT "/www"

static const char *TAG = "main";

static uint32_t counter = 0;
static bool is_tcp_server_ready = false;

esp_err_t start_rest_server(const char *base_path);

extern esp_err_t webserver_ws_send_data(const char *data, size_t len);

static void initialise_mdns(void)
{
    mdns_init();
    mdns_hostname_set(EXAMPLE_MDNS_HOST_NAME);
    mdns_instance_name_set(MDNS_INSTANCE);

    mdns_txt_item_t serviceTxtData[] = {
        {"board", "esp32"},
        {"path", "/"}};

    ESP_ERROR_CHECK(mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData,
                                     sizeof(serviceTxtData) / sizeof(serviceTxtData[0])));
}

esp_err_t init_fs(void)
{
    esp_vfs_spiffs_conf_t conf = {
        .base_path = EXAMPLE_WEB_MOUNT_POINT,
        .partition_label = NULL,
        .max_files = 5,
        .format_if_mount_failed = false};
    esp_err_t ret = esp_vfs_spiffs_register(&conf);

    if (ret != ESP_OK)
    {
        if (ret == ESP_FAIL)
        {
            ESP_LOGE(TAG, "Failed to mount or format filesystem");
        }
        else if (ret == ESP_ERR_NOT_FOUND)
        {
            ESP_LOGE(TAG, "Failed to find SPIFFS partition");
        }
        else
        {
            ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
        }
        return ESP_FAIL;
    }

    size_t total = 0, used = 0;
    ret = esp_spiffs_info(NULL, &total, &used);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
    }
    else
    {
        ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
    }
    return ESP_OK;
}

void send_json_data(void)
{
    // 获取内存信息
    uint32_t free_heap = esp_get_free_heap_size();
    uint32_t min_free_heap = esp_get_minimum_free_heap_size();

    // 创建 cJSON 对象
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        ESP_LOGE(TAG, "Failed to create root.");
        return;
    }

    if (1)
    {
        cJSON_AddStringToObject(root, "type", "status");
        cJSON_AddStringToObject(root, "eth_status", "Connected");

        net_ip_info_t *ip_info = network_manager_get_ip();
        if (ip_info != NULL)
        {
            cJSON_AddStringToObject(root, "eth_ip", ip_info->ip);
        }
        else
        {
            cJSON_AddStringToObject(root, "eth_ip", "");
        }

        char memory_usage[150];
        sprintf(memory_usage, "free_heap %lu/min_free_heap %lu", free_heap, min_free_heap);
        cJSON_AddStringToObject(root, "memory_usage", memory_usage);

        if(is_tcp_server_ready)
        {
            char tcp_server_info[150];
            sprintf(tcp_server_info, "%s:55555", ip_info->ip);
            cJSON_AddStringToObject(root, "tcp_server", tcp_server_info);
        }
        else
        {
            
        }

        char system_counter[32];
        sprintf(system_counter, "%lu", counter++);
        cJSON_AddStringToObject(root, "system_counter", system_counter);
    }

    if (0)
    {
        cJSON_AddStringToObject(root, "type", "control_response");

        char memory_usage[150];
        sprintf(memory_usage, "free_heap %lu/min_free_heap %lu", free_heap, min_free_heap);
        cJSON_AddStringToObject(root, "message", memory_usage);
    }

    // 转换 JSON 对象为字符串（无格式化输出）
    char *json_str = cJSON_PrintUnformatted(root);
    if (json_str == NULL)
    {
        ESP_LOGE(TAG, "cJSON_PrintUnformatted failed");
        cJSON_Delete(root);
        return;
    }

    // ESP_LOGI(TAG, "json data: %s", json_str);

    // 通过 WebSocket 发送 JSON 数据到 Web UI
    webserver_ws_send_data(json_str, strlen(json_str));

    // 释放内存
    free(json_str);
    cJSON_Delete(root);
}

void send_control_json_data(uint8_t *data, uint16_t len)
{
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        ESP_LOGE(TAG, "Failed to create root.");
        return;
    }

    cJSON_AddStringToObject(root, "type", "control_response");

    char memory_usage[256];
    memcpy(memory_usage, (char *)data, len);
    memory_usage[len] = '\0';
    cJSON_AddStringToObject(root, "message", memory_usage);

    char *json_str = cJSON_PrintUnformatted(root);
    if (json_str == NULL)
    {
        ESP_LOGE(TAG, "cJSON_PrintUnformatted failed");
        cJSON_Delete(root);
        return;
    }

    // ESP_LOGI(TAG, "json data: %s", json_str);

    // 通过 WebSocket 发送 JSON 数据到 Web UI
    webserver_ws_send_data(json_str, strlen(json_str));

    // 释放内存
    free(json_str);
    cJSON_Delete(root); 
}

void send_tcp_server_json_data(uint8_t *data, uint16_t len)
{
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        ESP_LOGE(TAG, "Failed to create root.");
        return;
    }

    cJSON_AddStringToObject(root, "type", "tcp_server_data");

    char memory_usage[256];
    memcpy(memory_usage, (char *)data, len);
    memory_usage[len] = '\0';
    cJSON_AddStringToObject(root, "message", memory_usage);

    char *json_str = cJSON_PrintUnformatted(root);
    if (json_str == NULL)
    {
        ESP_LOGE(TAG, "cJSON_PrintUnformatted failed");
        cJSON_Delete(root);
        return;
    }

    // ESP_LOGI(TAG, "json data: %s", json_str);

    // 通过 WebSocket 发送 JSON 数据到 Web UI
    webserver_ws_send_data(json_str, strlen(json_str));

    // 释放内存
    free(json_str);
    cJSON_Delete(root); 
}

void my_tcp_recv_callback(int client_fd, const uint8_t *data, size_t len, void *arg)
{
    printf("client_fd: %d\n", client_fd);
    printf("RX: %s\n", (char *)data);

    send_tcp_server_json_data(data, len);
}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    // ESP_ERROR_CHECK(esp_netif_init());
    // ESP_ERROR_CHECK(esp_event_loop_create_default());
    network_manager_init();
    initialise_mdns();
    netbiosns_init();
    netbiosns_set_name(EXAMPLE_MDNS_HOST_NAME);

    app_uart_init();

    // ESP_ERROR_CHECK(example_connect());

    ESP_ERROR_CHECK(init_fs());
    ESP_ERROR_CHECK(start_rest_server(EXAMPLE_WEB_MOUNT_POINT));

    if (tcp_server_start(55555, my_tcp_recv_callback, NULL) != ESP_OK) {
        ESP_LOGE(TAG, "Start TCP Server failed.");
    }
    else
    {
        is_tcp_server_ready = true;
        ESP_LOGI(TAG, "Start TCP Server OK");
    }

    while (1)
    {
        if (network_manager_is_connected())
        {
            // uint32_t free_heap = esp_get_free_heap_size();
            // uint32_t min_free_heap = esp_get_minimum_free_heap_size();

            // // 格式化为 JSON 字符串
            // char msg[128];
            // snprintf(msg, sizeof(msg),
            //          "{\"free_heap\": %u, \"min_free_heap\": %u}",
            //          free_heap, min_free_heap);

            // char *state = "{\"type\":\"status\",\"wifi_status\":\"Connected\",\"wifi_ip\":\"192.168.123.241\"}";
            // webserver_ws_send_data(state, strlen(state));

            send_json_data();
        }

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
